package com.aaa.ssm.util;


import com.aaa.ssm.entity.OperLog;
import com.aaa.ssm.service.OperLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @ fileName:LogRecordUtil
 * @ description:日志记录
 * @ author:李江波
 * @ createTime:2023/4/10 21:06
 * @ version:1.0.0
 */
@Component //不在三层之内的注解
@Aspect //标识当前类为通知类或者增强类
public class LogRecordUtil {
    @Resource //依赖注入 日志的service接口
    private OperLogService operLogService;
    @Resource //依赖注入 session
    private HttpSession session;

    @Resource   //依赖注入
    private HttpServletRequest request;
    /**
     * 方法名臣随意定义 主要作用编写切入点表达式
     * ||execution(* com.aaa.ssm.service.impl.*.update*(..)) 拦截update开头的方法
     */
    @Pointcut(value="execution(* com.aaa.ssm.service.impl.*.add*(..))" +
                    "||execution(* com.aaa.ssm.service.impl.*.update*(..))" +
                    "||execution(* com.aaa.ssm.service.impl.*.delete*(..))")
    //切面设置
    public void pointCut1(){
    }
    /**
     * 要排除的切入点配置
     */
//    @Pointcut("execution(* com.aaa.ss.controller.LoginLogController.*(..)) "+
//            "|| execution(* com.aaa.ss.controller.OperLogController.*(..))")
//    public void pointCutB() {
//    }
    /**
     * 封装格式化时间类
     * @return
     */
    private static String time(){
        //获取当前时间
        Date date = new Date();
        //实例化格式化时间类
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //format格式化时间
        String format = simpleDateFormat.format(date);
        return format;
    }
    /**
     * 后置通知 统一的日志记录方法
     * @param joinpoint
     */
    @AfterReturning(pointcut = "pointCut1()") //后置通知注解
    public void recordLog(JoinPoint joinpoint){
        //实例化日志文件
        OperLog operLog = new OperLog();
        //获取操作人的姓名
        String loginA = (String) session.getAttribute("loginA");
       //joinpoint.getArgs()获取所有的执行方法的参数
        Object[] args = joinpoint.getArgs();
        //获取数组是否为空
        //定义参数
        String name=null;
        if (args!=null &&args.length>0){
            //通过反射获取对象---利用getName()获取姓名
            name = args[0].getClass().getName();

        }

        //通过aop提供的Joinpoint获取到业务执行方法的名称
        String methodName = joinpoint.getSignature().getName(); //设置操作日志类型   1 添加 2 更新  3删除
        //获取执行类的名称  如果业务类是DeptServiceImpl 获得到就是com.aaa.ssm.service.impl.DeptServiceImpl
        //     如果业务类是MenuServiceImpl  获取到的就是com.aaa.ssm.service.impl.MenuServiceImpl
        String targetName = joinpoint.getTarget().getClass().getName();

        //设置操作日志类型   1 添加 2 更新  3删除
        int bzType = ConstantUtil.OperLogBussinessType.ADD;
        //判断拦截到方法是否以update开头
        if(methodName.startsWith("update") || methodName.startsWith("edit")){
            bzType =  ConstantUtil.OperLogBussinessType.UPDATE;
        }else if(methodName.startsWith("delete")){
            bzType =  ConstantUtil.OperLogBussinessType.DELETE;
        }

        //获取url
        StringBuffer requestURL = request.getRequestURL();

        //为操作方法赋值
        operLog.setMethod(targetName+"."+methodName);
        //为操作类型赋值
        operLog.setBusinessType(bzType);
        //获取执行Ip
        String remoteAddr = request.getRemoteAddr();
        //为模块赋值
        operLog.setTitle("后台管理");
        //为操作时间赋值
        operLog.setOperTime(time());
        //为主机地址赋值
        operLog.setOperIp(remoteAddr);
        //为操作人员名赋值
        operLog.setOperName(loginA);
        //为操作类型赋值
        operLog.setOperatorType(ConstantUtil.OperLogOperatorType.BACKUSER);
        //为部门名称赋值
        operLog.setDeptName("");
        //请求的URl
        operLog.setOperUrl(requestURL.toString());
        //操作地点
        operLog.setOperLocation("内网IP");
        //为 operLog 的请求参数赋值
        operLog.setOperParam(name);
        //操作状态
        operLog.setStatus(0);
        //错误信息
        operLog.setErrorMsg("异常名称");
        //调用添加方法
        operLogService.OpeLog(operLog);
    }
}